package com.freak.kotlinfitnessserver.bt

import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.bluetooth.BluetoothServerSocket
import android.bluetooth.BluetoothSocket
import androidx.appcompat.app.AppCompatActivity
import com.freak.kotlinfitnessserver.app.App
import com.freak.kotlinfitnessserver.util.LogUtil
import com.freak.kotlinfitnessserver.util.ToastUtil
import java.io.DataInputStream
import java.io.DataOutputStream
import java.io.File
import java.util.UUID
import java.util.concurrent.Executor
import java.util.concurrent.Executors

abstract class BaseBluetooth(bluetoothListener: BluetoothListener) {
    companion object {
        const val TAG: String = "BaseBluetooth"
        val SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
    }


    private var mSocket: BluetoothSocket? = null

    var mDataOutputStream: DataOutputStream? = null

    /**
     * 是否正在读取
     */
    private var isRead = false

    private val mBluetoothListener: BluetoothListener = bluetoothListener

    val mExecutor: Executor = Executors.newCachedThreadPool()

    var mBluetoothAdapter: BluetoothAdapter? = null

    var mBluetoothManager: BluetoothManager? = null
    open fun init() {
        mBluetoothManager = App.getContext()
            .getSystemService(AppCompatActivity.BLUETOOTH_SERVICE) as BluetoothManager
        mBluetoothManager ?: let {
            ToastUtil.toastShort("mBluetoothManager not support")
            return
        }
        mBluetoothAdapter = mBluetoothManager?.adapter
        if (mBluetoothAdapter == null) {
            ToastUtil.toastShort("bluetooth not support")
            return
        }
    }

    /**
     * 循环读取对方数据(若没有数据，则阻塞等待)
     *
     * @param socket BluetoothSocket
     */
    fun startLoopRead(socket: BluetoothSocket) {
        mSocket = socket
        mSocket ?: let {
            return
        }
        mExecutor.execute {
            loopRead()
        }
    }

    /**
     * 循环读取对方数据(若没有数据，则阻塞等待)
     *
     */
    private fun loopRead() {
        try {
            if (mSocket!!.isConnected) {
                LogUtil.i(TAG, "mSocket is Connect")
                return
            }
            mSocket!!.connect()
            notifyUI(BluetoothListener.CONNECTED, mSocket!!.remoteDevice)
            mDataOutputStream = DataOutputStream(mSocket!!.outputStream)
            val dataInputStream = DataInputStream(mSocket!!.inputStream)
            isRead = true
            // 死循环读取数据
            while (isRead) {
                readMessage(dataInputStream)
            }
        } catch (e: Exception) {
            LogUtil.e(TAG, "loopRead Exception $e")
            close()
        }
    }

    /**
     * 关闭Socket连接
     */
    open fun close() {
        try {
            isRead = false
            mSocket!!.close()
            notifyUI(BluetoothListener.DISCONNECTED, null)
        } catch (e: Throwable) {
            e.printStackTrace()
        }
    }

    /**
     * 当前设备与指定设备是否连接
     * @param device BluetoothDevice
     */
    fun isConnected(device: BluetoothDevice?): Boolean {
        val connected = mSocket != null && mSocket!!.isConnected
        return if (device == null) connected else connected && mSocket!!.remoteDevice == device
    }

    /**
     * 回调到UI侧
     */
    fun notifyUI(state: Int, objects: Any?) {
        mBluetoothListener.socketNotify(state, objects)
    }

    fun mkdirs(filePath: String?) {
        val mk = filePath?.let { File(it).mkdirs() }
        LogUtil.i(TAG, "mkdirs: $mk")
    }

    abstract fun readMessage(dataInputStream: DataInputStream)
}